﻿using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Threading.Tasks;
using Ch12.Models;
using Devonline.Core;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace Ch12.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class HousesController : ControllerBase
    {
        private readonly ILogger<HousesController> _logger;
        private readonly ApplicationDbContext _context;
        public HousesController(ILogger<HousesController> logger, ApplicationDbContext context)
        {
            _logger = logger;
            _context = context;
        }

        /// <summary>
        /// 计算房产信息
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> Execute()
        {
            _logger.LogInformation("step1: retreve house and account, proprietor!");
            var houses = await _context.Houses
                .Where(x => x.State == Models.DataState.Available)
                .Include(x => x.Account)
                .Include(x => x.Proprietor)
                .ToListAsync();

            _logger.LogInformation("step2: retrieve payment record!");
            var paymentRecords = await _context.PaymentRecords.ToListAsync();

            _logger.LogInformation("step3: calculate house result!");
            var list = new Dictionary<string, HouseResultViewModel>();
            Parallel.ForEach(houses, house =>
            {
                var viewModel = new HouseResultViewModel
                {
                    Id = house.Id,
                    Name = (house.Proprietor?.Name ?? "张三").GetHashCode<SHA256>(),
                    Position = (house.Position.IsNullOrWhiteSpace() ? "不详" : house.Position).GetHashCode<MD5>(),
                    Amount = house.Account?.Amount ?? 0
                };

                lock (list)
                {
                    list.Add(house.Id, viewModel);
                }
            });

            _logger.LogInformation("step4: set payment amount to house result!");
            Parallel.ForEach(paymentRecords, paymentRecord =>
            {
                if (list.ContainsKey(paymentRecord.HouseId))
                {
                    lock (list)
                    {
                        var viewModel = list[paymentRecord.HouseId];
                        if (viewModel != null)
                        {
                            viewModel.PaymentAmount += paymentRecord.Amount;
                        }
                    }
                }
            });

            _logger.LogInformation("now all house and account payment record ware process complete!");
            return Ok();
        }
    }
}
